#!/usr/bin/env python
# encoding=utf-8
#codeby     道长且阻
#email      ydhcui@suliu.net/QQ664284092
#website    http://www.suliu.net


import os
import time
import json
from functools import reduce

import tornado
import tornado.web
#from tornado.escape import json_decode,json_encode
#from jinja2 import Environment, FileSystemLoader

import models
from client import TaskManage

class Route(object):
    _routes = {}
    def __init__(self, pattern, kwargs={}, name=None, host='.*$'):
        self.pattern = pattern #'/api' + pattern
        self.kwargs = {}
        self.name = name
        self.host = host

    def __call__(self, handler_class):
        spec = tornado.web.url(self.pattern, handler_class, self.kwargs, name=self.name)
        self._routes.setdefault(self.host, []).append(spec)
        return handler_class

    @classmethod
    def routes(cls, application=None):
        if application:
            for host, handlers in cls._routes.items():
                application.add_handlers(host, handlers)
        else:
            return reduce(lambda x,y:x+y, cls._routes.values()) if cls._routes else []

class BaseHandler(tornado.web.RequestHandler):

    '''
    def get_template_path(self):
        """ 获取模板路径 """
        return self.settings['template_path']
    
    def create_template_loader(self, template_path):
        """ 根据template_path创建相对应的Jinja2 Environment """
        temp_path = template_path
        if isinstance(template_path, (list, tuple)):
            temp_path = template_path[0]
        env = BaseHandler._path_to_env.get(temp_path)
        if not env:
            _loader = FileSystemLoader(template_path)
            env = Environment(loader = _loader)
            #为了和vue兼容 修改jiaja的模板标识符
            env.variable_start_string = '{[ '
            env.variable_end_string = ' ]}'
            BaseHandler._path_to_env[temp_path] = env
        return env
    

    def render_string(self, template_name, **kwargs):
        """ 使用Jinja2模板引擎 """
        env = self.create_template_loader(self.get_template_path())
        namespace = self.get_template_namespace()
        namespace.update(kwargs)
        return env.get_template(template_name).render(**namespace)
    '''

    def get_current_user(self):
        #if self.request.headers.get("X-Token")=='admin':
        #if self.get_secure_cookie('u')=='1':
        return True

    @tornado.web.authenticated
    @tornado.web.asynchronous
    @tornado.gen.coroutine
    def post(self):
        result = {'code':0}
        try:
            data = self._desdecode(self.request.body)
            token = data.get('token')
            action = data.get('action')
            kwargs = data.get('kwargs')
            action = '_%s_action'%action
            if hasattr(self,action):
                result.update(getattr(self,action)(**kwargs))
            else:
                raise Exception('action not in model')
        except Exception as e:
            result['code'] = e
        self.write(result)
        self.finish()

    def _desdecode(self,data):
        res = json.loads(data.decode())
        print(res)
        return res

##################################################################################
@Route(r'/user')
class UserHandler(BaseHandler):
    def post(self):
        result = {'code':0}
        try:
            data = self._desdecode(self.request.body)
            action = data.get('action')
            kwargs = data.get('kwargs')
            action = '_%s_action'%action
            if hasattr(self,action):
                result.update(getattr(self,action)(**kwargs))
            else:
                raise Exception('action not in model')
        except Exception as e:
            result['code'] = e
        self.write(result)
        self.finish()

    def _login_action(self,**kwargs):
        username = kwargs.get('name')
        password = kwargs.get('password')
        M = models.User
        try:
            R = M.get(M.uname==username,M.upwd==password)
            self.set_secure_cookie('u',str(R.uid))
            return {'token':str(R.token),'email':str(R.uemail)}
        except M.DoesNotExist:
            return {'code':'用户名密码错误'}
    
    def _reg_action(self,**kwargs):
        pass

@Route(r'/project')
class ProjectHandler(BaseHandler):
    def _select_action(self,**kwargs):
        return {}
    
    def _create_action(self,**kwargs):
        pjname = kwargs.get('pjname')
        pjdesc = kwargs.get('pjdesc')
        M = models.Project 
        R,cd = M.get_or_create(pj_name=pjname,pj_desc=pjdesc)
        return {'pjid':str(R.pj_id),'pjname':str(R.pj_name),'iscd':cd}

    def _delete_action(self,**kwargs):
        isdeldata = kwargs.get('isdeldata',0)


    def _getproject_action(self,**kwargs):
        pass 
    
    def _view_action(self,**kwargs):
        pjid = kwargs.get('pjid')
        return {
            'pjid': str(R.pj_id), 
            'pjname': str(R.pj_name), 
            'pjdesc': str(R.pj_desc),
            'reportpath': str(R.reportpath),
            'createdate': str(R.createdate),
            'finishdate': str(R.finishdate),
            'settings':{},
            'tasks':[{}],
            'vulresult':{}
        }

@Route(r'/task')
class TaskHandler(BaseHandler):
    def _gettask_action(self,**kwargs):
        M = models.Project 
        query = M.select().where(M.finishdate==0).order_by(M.createdate).paginate(0,10)
        return {
            'tasks':TaskManage.gettasks(),
            'projects':[{'pjid':Q.pj_id,'pjname':Q.pj_name} for Q in query]
        }
    
    def _create_action(self,**kwargs):
        pjid = kwargs.get('pjid')
        tkhost = kwargs.get('tkhost')
        tkdesc = kwargs.get('tkdesc')
        tkmods = kwargs.get('mods')
        P = models.Project 
        M = models.ScanTask 
        MP = P.get(P.pj_id==pjid)
        result = []
        for mod in tkmods:
            R,cd = M.get_or_create(project=MP,task_name=mod,task_host=tkhost,task_desc=tkdesc)
            result.append({
                'thid':str(R.task_id),
                'tkname':str(R.task_name),
                'tkhost':str(R.task_host)})
        return {'result':result}


@Route(r'/scan.task')
class ScanTaskHandler(BaseHandler):
    def _create_action(self,**kwargs):
        host = kwargs.get('host')
        name = kwargs.get('name')

    def _select_action(self,**kwargs):
        ''''''
        page    = int(kwargs.get('page',0))
        num     = int(kwargs.get('num',20))
        query   = self.select().order_by(self.createdate).paginate(page,num)
        return {'result':[
                {'id':Q.task_id,
                 'host':Q.task_host,
                 'note':Q.task_note,
                 'state':Q.task_state,
                 'level':Q.task_level,
                 'starttime':Q.createdate,
                 'endtime':Q.finishdate
        } for Q in query]}

    def _delete_action(self,**kwargs):
        taskid = kwargs.get('taskid')
        self.delete().where(self.task_id==taskid)
        self.execute()
        return 'ok'

    def _view_action(self,**kwargs):
        taskid = kwargs.get('taskid')


@Route(r'/scan\.port')
class ScanPortHandler(BaseHandler):
    def _select_action(self,**kwargs):
        act = kwargs.get('act','host')
        query = self.select().where(self.host==kwargs.get(act))
        return {'result':[
                {'host':Q.host,
                 'port':Q.port,
                 'name':Q.name,
                 'state':Q.state
        } for Q in query]}

@Route(r'/scan\.http')
class ScanDomainHandler(BaseHandler):
    def _select_action(self,**kwargs):
        host = kwargs.get('host')
        port = kwargs.get('port')
        query = self.get(self.host==host,self.port==port)


